home *** CD-ROM | disk | FTP | other *** search
- _PROGRAMMING WINDOWS USING STATE TABLES_
- by Michael A. Bertrand and William R. Welch
-
- [LISTING ONE]
-
- /***********DRAW.H : header file for DRAW.C **************************/
-
- #define WAITING 0 /* the possible values for variable iState in */
- #define DRAWING 1 /* Tool() are WAITING and DRAWING */
-
- /* These constants are the possible values for iMenuChoice, the variable
- * recording the user's menu choice. The old menu choice must be stored
- * so the check mark can be removed from the menu when a new menu choice
- * is made. Do not change. */
- #define IDM_RECT 100
- #define IDM_ROUND_RECT 101
- #define IDM_ELLIPSE 102
- #define IDM_LINE 103
- #define IDM_ABOUT 104
-
- /* These constants are the possible values for iFigType, the variable
- * recording the current FIGURE, as chosen through the menu. The value is
- * also stored in the iType field in faList[] and is used to determine
- * which drawing function is called upon from DrawFig[], the array of
- * pointers to functions; since these values are indices into an array,
- * starting at 0, they may not be changed. */
- #define FT_RECT (IDM_RECT - IDM_RECT)
- #define FT_ROUND_RECT (IDM_ROUND_RECT - IDM_RECT)
- #define FT_ELLIPSE (IDM_ELLIPSE - IDM_RECT)
- #define FT_LINE (IDM_LINE - IDM_RECT)
-
- /* maximum number of FIGUREs in faList[] */
- #define MAX_FIGS 1000
-
- /* FIGUREs in faList[]: rectangle, rounded rectangle, ellipse, line */
- typedef struct
- { int iType;
- RECT rsCoord;
- } FIGURE;
-
- /* global variables */
- FIGURE faList[MAX_FIGS]; /* List of FIGUREs */
- int iListSize; /* tally number of displayed FIGUREs */
- HANDLE hInst; /* current instance */
- RECT rClient; /* client area in scr coords for ClipCursor() */
-
- /* function prototypes */
- long FAR PASCAL WndProc(HWND hWnd, unsigned iMessage, WORD wParam,
- LONG lParam);
- void NEAR PASCAL Tool(HWND hWnd, unsigned iMessage, LONG lParam,int iFigType);
- BOOL FAR PASCAL DrawRoundRect(HDC hDC, int x1, int y1, int x2, int y2);
- BOOL FAR PASCAL DrawLine(HDC hDC, int x1, int y1, int x2, int y2);
- BOOL FAR PASCAL AboutDraw(HWND hDlg, unsigned message, WORD wParam,
- LONG lParam);
- /* DrawFig[] is an array of pointers to FAR PASCAL functions, each with parms
- * (HDC,int,int,int,int) and returning BOOL. Note Rectangle() and Ellipse() are
- * MS Windows GDI calls, while DrawRoundRect() and DrawLine() are our calls. */
- BOOL (FAR PASCAL *DrawFig[4])(HDC hDC, int x1, int y1, int x2, int y2)
- = {Rectangle, DrawRoundRect, Ellipse, DrawLine};
-
-
-
-
- [LISTING TWO]
-
- /******* DRAW.C by Michael A. Bertrand and William R. Welch. *******/
-
- #include <windows.h>
- #include "draw.h"
-
- int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine,
- int nCmdShow)
- /* hInstance : current instance handle
- * hPrevInstance : previous instance handle
- * lpszCmdLine : current command line
- * nCmdShow : display either window or icon
- */
- { static char szAppName [] = "Draw";
- static char szIconName[] = "DrawIcon";
- static char szMenuName[] = "DrawMenu";
-
- HWND hWnd; /* handle to WinMain's window */
- MSG msg; /* message dispached to window */
- WNDCLASS wc; /* for registering window */
-
- /* Save instance handle in global var so can use for "About" dialog box. */
- hInst = hInstance;
-
- if (!hPrevInstance) /* Register application window class. */
- { wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = WndProc; /* function to get window's messages */
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, szIconName);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = szMenuName; /* menu resource in RC file */
- wc.lpszClassName = szAppName; /* name used in call to CreateWindow() */
- if (!RegisterClass(&wc))
- return(FALSE);
- }
- /* Initialize specific instance. */
- hWnd = CreateWindow(szAppName, /* window class */
- szAppName, /* window caption */
- WS_OVERLAPPEDWINDOW, /* normal window style */
- CW_USEDEFAULT, /* initial x-position */
- CW_USEDEFAULT, /* initial y-position */
- CW_USEDEFAULT, /* initial x-size */
- CW_USEDEFAULT, /* initial y-size */
- NULL, /* parent window handle */
- NULL, /* window menu handle */
- hInstance, /* program instance handle */
- NULL); /* create parameters */
-
- ShowWindow(hWnd, nCmdShow); /* display the window */
- UpdateWindow(hWnd); /* update client area; send WM_PAINT */
-
- /* Read msgs from app que and dispatch them to appropriate win function.
- * Continues until GetMessage() returns NULL when it receives WM_QUIT. */
- while (GetMessage(&msg, NULL, NULL, NULL))
- { TranslateMessage(&msg); /* process char input from keyboard */
- DispatchMessage(&msg); /* pass message to window function */
- }
- return(msg.wParam);
- }
- /****************************************************************/
- long FAR PASCAL WndProc(HWND hWnd,unsigned iMessage, WORD wParam, LONG lParam)
- /* IN: hWnd : handle to window
- * iMessage : message type
- * wParam : drawing tool selected from menu (when WM_COMMAND msg)
- * lParam : mouse coords (x == loword, y == hiword) */
- { static int iMenuChoice = IDM_RECT; /* default menu choice */
- static int iFigType = FT_RECT; /* default figure type */
- HDC hDC; /* must generate our own handle to DC to draw */
- HMENU hMenu; /* handle for drop down menu */
- PAINTSTRUCT ps; /* needed when receive WM_PAINT message */
- int ndx; /* to traverse faList[] when draw it */
- FARPROC lpProcAbout; /* pointer to "AboutDraw" function */
- POINT pt; /* for ClientToScreen() */
-
- switch(iMessage)
- { case WM_SIZE: /*convert client coords to scrn coords for ClipCursor()*/
- pt.x = pt.y = 0;
- ClientToScreen(hWnd, &pt);
- rClient.left = pt.x;
- rClient.top = pt.y;
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- ClientToScreen(hWnd, &pt);
- rClient.right = pt.x;
- rClient.bottom = pt.y;
- break;
- case WM_COMMAND:
- switch(wParam)
- { case IDM_RECT:
- case IDM_ROUND_RECT:
- case IDM_ELLIPSE:
- case IDM_LINE:
- /* New FIGURE chosen by user : uncheck old choice and check new
- * choice on menu; reset iMenuChoice according to user choice. */
- hMenu = GetMenu(hWnd);
- CheckMenuItem(hMenu, iMenuChoice, MF_UNCHECKED);
- CheckMenuItem(hMenu, iMenuChoice = wParam, MF_CHECKED);
- /* User has chosen new FIGURE : set iFigType accordingly. */
- iFigType = iMenuChoice - IDM_RECT;
- break; /* case IDM_LINE ... */
- case IDM_ABOUT:
- /* "About" chosen by user : call "AboutDraw" function. */
- lpProcAbout = MakeProcInstance(AboutDraw, hInst);
- DialogBox (hInst, "AboutDraw", hWnd, lpProcAbout);
- FreeProcInstance(lpProcAbout);
- break; /* IDM_ABOUT */
- } /* switch(wParam) */
- break; /* WM_COMMAND */
- case WM_LBUTTONDOWN:
- case WM_MOUSEMOVE:
- case WM_LBUTTONUP:
- /* Mouse events passed on to Tool() for processing. */
- Tool(hWnd, iMessage, lParam, iFigType);
- break; /* WM_LBUTTONDOWN... */
- case WM_PAINT:
- /* Repaint window when resized. */
- hDC = BeginPaint(hWnd, &ps);
- /* Draw list of FIGUREs. */
- for (ndx = 0; ndx < iListSize; ndx++)
- DrawFig[faList[ndx].iType](hDC, faList[ndx].rsCoord.left,
- faList[ndx].rsCoord.top,
- faList[ndx].rsCoord.right,
- faList[ndx].rsCoord.bottom);
- EndPaint(hWnd, &ps);
- break; /* WM_PAINT */
- case WM_DESTROY:
- /* Destroy window when application terminated. */
- PostQuitMessage(0);
- break; /* WM_DESTROY */
- default:
- return(DefWindowProc(hWnd, iMessage, wParam, lParam));
- } /* switch(iMessage) */
- return(0L);
- }
- /****************************************************************/
- void NEAR PASCAL Tool(HWND hWnd, unsigned iMessage, LONG lParam, int iFigType)
- /* Process mouse event and draw.
- * IN: hWnd : handle to window
- * iMessage : mouse event (WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP)
- * lParam : mouse coords (x == loword, y == hiword)
- */
- { static int x1, y1; /* coordinates of button-down point */
- static int x2, y2; /* coordinates of mouse */
- static int iState; /* WAITING or DRAWING */
- HDC hDC; /* must generate our own handle to DC to draw */
- switch(iMessage)
- { case WM_LBUTTONDOWN:
- /* Protect array from overflow : if array full, notify and out. */
- if (iListSize == MAX_FIGS)
- { MessageBox(hWnd,"Figure array full","Note",MB_ICONEXCLAMATION|MB_OK);
- break; /* WM_LBUTTONDOWN */
- }
- /* If not drawing, reset iState and store button-down point. */
- if (iState == WAITING)
- { ClipCursor(&rClient); /* restrict cursor */
- iState = DRAWING; /* starting drag */
- x1 = x2 = LOWORD(lParam); /* store user point in statics */
- y1 = y2 = HIWORD(lParam);
- }
- break; /* WM_LBUTTONDOWN */
- case WM_MOUSEMOVE:
- /* If drawing, erase old figure and draw new one at mouse. */
- if (iState == DRAWING)
- { hDC = GetDC(hWnd);
- SetROP2(hDC, R2_NOTXORPEN); /* draw in XOR */
- DrawFig[iFigType](hDC, x1, y1, x2, y2); /* erase old */
- x2 = LOWORD(lParam); /* get 2nd user pt */
- y2 = HIWORD(lParam);
- DrawFig[iFigType](hDC, x1, y1, x2, y2); /* draw new */
- ReleaseDC(hWnd, hDC);
- }
- break; /* WM_MOUSEMOVE */
- case WM_LBUTTONUP:
- /* If drawing, write in COPY mode and store in faList[]. */
- if (iState == DRAWING)
- { ClipCursor(NULL); /* no longer restrict cursor */
- iState = WAITING; /* ending draw */
- hDC = GetDC(hWnd);
- SetROP2(hDC, R2_COPYPEN); /* COPY pen for final FIGURE */
- DrawFig[iFigType](hDC, x1, y1, x2, y2); /* draw FIGURE */
- ReleaseDC(hWnd, hDC);
- faList[iListSize].iType = iFigType; /* put FIGURE in faList[] */
- faList[iListSize].rsCoord.left = x1;
- faList[iListSize].rsCoord.top = y1;
- faList[iListSize].rsCoord.right = x2;
- faList[iListSize].rsCoord.bottom = y2;
- iListSize++; /* bump tally, since just added figure to list */
- }
- break; /* WM_LBUTTONUP */
- } /* switch(iMessage) */
- }
- /****************************************************************/
- BOOL FAR PASCAL DrawRoundRect(HDC hDC, int x1, int y1, int x2, int y2)
- /* IN: hDC : display context in which to draw
- * x1, y1 : coordinates of first corner
- * x2, y2 : coordinates of second corner
- * RET: returns BOOL for consistency with GDI's Rectangle() and Ellipse()
- * NOTE: GDI's RoundRect() is used to draw, but RoundRect() requires x-
- * and y-diameters of ellipse used for rounding. This routine sets
- * the common diameter equal to half the smallest side, then calls
- * RoundRect(). Array DrawFig[] contains a pointer to this function.
- */
- { int dx, dy; /* sides of rectangle, as positive values */
- int diameter; /* diameter of circle used for rounding */
-
- dx = (x1 < x2) ? (x2 - x1) : (x1 - x2); /* x-side of rect (positive) */
- dy = (y1 < y2) ? (y2 - y1) : (y1 - y2); /* y-side of rect (positive) */
- diameter = (dx < dy) ? dx/2 : dy/2; /* half smallest side */
- RoundRect(hDC, x1, y1, x2, y2, diameter, diameter); /* call GDI */
- return(TRUE);
- }
- /****************************************************************/
- BOOL FAR PASCAL DrawLine(HDC hDC, int x1, int y1, int x2, int y2)
- /*
- * IN: hDC : display context in which to draw
- * x1, y1 : coordinates of first endpoint
- * x2, y2 : coordinates of second endpoint
- * RET: returns BOOL for consistency w/GDI's Rectangle() and Ellipse().
- * NOTE: Array DrawFig[] contains a pointer to this function.
- */
- { MoveTo(hDC, x1, y1); /* MoveTo() and LineTo() are GDI calls. */
- LineTo(hDC, x2, y2);
- return(TRUE);
- }
- /****************************************************************/
- BOOL FAR PASCAL AboutDraw(HWND hDlg,unsigned iMessage,WORD wParam,LONG lParam)
- /* Application's "About" dialog box function.
- * IN: hDlg : handle to dialog box
- * iMessage : message type
- * wParam : auxiliary message info (act on IDOK, IDCANCEL)
- * lParam : unused
- * RET: Return TRUE if processed appropriate message, FALSE otherwise.
- */
- { switch (iMessage)
- { case WM_INITDIALOG: /* initialize dialog box */
- return (TRUE);
- case WM_COMMAND: /* received a command */
- /* IDOK if OK box selected; IDCANCEL if system menu close command */
- if (wParam == IDOK || wParam == IDCANCEL)
- { EndDialog(hDlg, TRUE); /* exit dialog box */
- return(TRUE); /* did proccess message */
- }
- break; /* WM_COMMAND */
- } /* switch (iMessage) */
- return (FALSE); /* did not process message */
- }
-
-
-
-
- [LISTING THREE]
-
- #*************** DRAW : Make file for DRAW.C ***************************
- # To make program : NMAKE DRAW
- # Linker and Resource Compiler: draw.exe depends on draw.obj draw.def draw.res
- # Linker options as follows :
- # /A:16 : align on paragraphs
- # /CO : add symbol information to EXE for CodeView
- # /NOD : don't search default libs (use only those in link response file)
-
- draw.exe: draw.obj draw.def draw.res
- link /A:16 /CO /NOD draw,,, libw slibcew, draw.def
- rc draw.res
-
- # Microsoft C Compiler : draw.obj contingent on draw.c, draw.h
- # Compiler options as follows :
- # -c : compile only
- # -Gs : remove stack probe before function calls
- # -Gw : for MS Windows
- # -Od : disable code optimization to help with debugging
- # -W3 : highest warning level (flags ANSI incompatibilities)
- # -AS : small model
- # -Zp : pack structures (required by MS Windows)
- # -Zi : add symbol information to OBJ for CodeView
- draw.obj: draw.c draw.h
- cl -c -Gsw -Od -W3 -AS -Zpi draw.c
-
- # Resource Compiler : draw.res contingent on draw.rc, draw.h
- draw.res: draw.rc draw.h
- rc -r -v draw.rc
-
-
-
-
- [LISTING FOUR]
-
- ;;**************DRAW.DEF : Definition file for DRAW.C**************
- NAME DRAW
- DESCRIPTION 'MS Windows Draw Program (c) 1990 M. Bertrand & W. Welch'
- EXETYPE WINDOWS
- STUB 'WINSTUB.EXE'
- CODE MOVEABLE PRELOAD
- DATA MOVEABLE PRELOAD SINGLE
- HEAPSIZE 1024
- STACKSIZE 4096
- EXPORTS WndProc
- AboutDraw
-
-
-
- [LISTING FIVE]
-
- /************ DRAW.RC : resource file for DRAW.C *******************/
-
- #include "windows.h"
- #include "draw.h"
-
- DrawIcon ICON DRAW.ICO
-
- DrawMenu MENU
- BEGIN
- POPUP "&Tool"
- BEGIN
- MENUITEM "&Rectangle", IDM_RECT, CHECKED
- MENUITEM "R&ounded rectangle", IDM_ROUND_RECT
- MENUITEM "&Ellipse", IDM_ELLIPSE
- MENUITEM "&Line", IDM_LINE
- MENUITEM Separator
- MENUITEM "&About Draw...", IDM_ABOUT
- END
- END
-
- /* "AboutDraw" dialog box contains 3 types of controls :
- * CTEXT to display centered text at x-coordinates 8, 24, 40, 56
- * ICON to display DRAW's icon at coords relative (20,20)
- * DEFPUSHBUTTON to display 32x14 OK push button at coords (60,74)
- */
- AboutDraw DIALOG 30, 30, 150, 94
- CAPTION "About Draw"
- STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
- BEGIN
- CTEXT "Microsoft Windows" -1, 0, 8, 152, 8
- CTEXT "Draw" -1, 0, 24, 152, 8
- CTEXT "Copyright (c) 1990" -1, 0, 40, 152, 8
- CTEXT "Michael A. Bertrand and William R. Welch" -1, 0, 56, 152, 8
- ICON "DrawIcon" -1, 20, 20, 19, 26
- DEFPUSHBUTTON "&OK" IDOK, 60, 74, 32, 14, WS_GROUP
- END
-